<#include "/includes/vars.inc">  
<@pp.dropOutputFile />

<#list entities.entity as entity>
    <#assign entityName = entity.@name>
    <#assign fileName = "${testJavaDir}${packageDir}/util/"+entityName?cap_first+"DataGenerator.java">
    <@pp.changeOutputFile name="${fileName}" />
		
package ${project.@rootPackage}.util;

import ${project.@rootPackage}.domain.${entityName};
<#list entity.column.@type as enum>
    <#if enums.enum.@name?seq_contains(enum)>
import ${project.@rootPackage}.domain.enums.${enum};
    </#if>
</#list>
<#list entity["one-to-one"] as rel>
import ${project.@rootPackage}.domain.${rel.@entity};
</#list>
<#list entity["many-to-one"] as rel>
import ${project.@rootPackage}.domain.${rel.@entity};
</#list> 
import ${project.@rootPackage}.service.${entityName}Service;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Data generator for class ${entityName}
 * <#if project.@author[0]??>@author ${project.@author}</#if>
 */
@Component
public class ${entityName}DataGenerator {
    @Autowired
    private ${entityName}Service service;
	
	<#list entity["one-to-one"] as rel>
    @Autowired
    private ${rel.@entity}DataGenerator ${rel.@entity?uncap_first}DataGenerator;
	
	</#list>
	<#list entity["many-to-one"] as rel>
		<#if rel.@entity != entityName>
    @Autowired
    private ${rel.@entity}DataGenerator ${rel.@entity?uncap_first}DataGenerator;
		</#if>
		
	</#list>
    private List<${entityName}> data;
    
    private Random rnd = new Random();
    
    public ${entityName} getNewTransientEntity(int index) {
        ${entityName} obj = new ${entityName}();
        <#list entity.column as column>    
            <#if column.@primary[0]="false">
        set${column.@name?cap_first}(obj, index);
            </#if>
        </#list>
        <#list entity["one-to-one"] as rel>
        obj.set${rel.@name?cap_first}((${rel.@entity})${rel.@entity?uncap_first}DataGenerator.getRandomEntity());
        </#list>
        <#list entity["many-to-one"] as rel>
        	 <#if rel.@entity != entityName>
        obj.set${rel.@name?cap_first}((${rel.@entity})${rel.@entity?uncap_first}DataGenerator.getRandomEntity());
        	<#else> 
       	//obj.set${rel.@name?cap_first}((${rel.@entity})getRandomEntity()); //Problem: infinite loop when call from init()
       	obj.set${rel.@name?cap_first}(null); 
        	</#if>
        </#list>
        return obj;
    }
	
    <#list entity.column as column>
        <#if column.@primary[0]="true">
        <#elseif enums.enum.@name?seq_contains(column.@type)>
    public void set${column.@name?cap_first}(${entityName} obj, int index){
        obj.set${column.@name?cap_first}((${column.@type})ValueGenerator.getRandomEnum(${column.@type}.class));
    }
    	<#elseif embeddables.embeddable.@name?seq_contains(column.@type)>
     public void set${column.@name?cap_first}(${entityName} obj, int index){
     	<#list embeddables.embeddable as embed>
			<#if embed.@name=column.@type>
				<#list embed.column as col>
        obj.get${column.@name?cap_first}().set${col.@name?cap_first}(ValueGenerator.getRandom${col.@type?cap_first}());
        		</#list>
        	</#if>
        </#list>
    }	
        <#else>
    public void set${column.@name?cap_first}(${entityName} obj, int index){
        obj.set${column.@name?cap_first}(ValueGenerator.getRandom${column.@type?cap_first}());
    }
        </#if>
    </#list>
	
    public ${entityName} getRandomEntity() {
        init();
        ${entityName} obj = data.get(rnd.nextInt(data.size()));
        Long id = obj.getId();
        return service.findById(id);
    }
    
    public Long getRandomIndex() {
        init();
        ${entityName} obj = data.get(rnd.nextInt(data.size()));
        return obj.getId();
    }
    
    public ${entityName} getSpecificEntity(int index) {
        init();
        if (index < 0) index = 0;
        if (index > (data.size() - 1)) index = data.size() - 1;
        ${entityName} obj = data.get(index);
        Long id = obj.getId();
        return service.findById(id);
    }
    
    public void init() {
        service.getDao().clear();
        data = service.findAll();
        if (data == null) throw new IllegalStateException("Find entries implementation for '${entityName}' illegally returned null");
        if (!data.isEmpty()) {
            return;
        }
        
        data = new ArrayList<${entityName}>();
        for (int i = 0; i < 10; i++) {
            ${entityName} obj = getNewTransientEntity(i);
            try {
                service.create(obj);
            } catch (ConstraintViolationException e) {
                StringBuilder msg = new StringBuilder();
                for (Iterator<ConstraintViolation<?>> it = e.getConstraintViolations().iterator(); it.hasNext();) {
                    ConstraintViolation<?> cv = it.next();
                    msg.append("[").append(cv.getConstraintDescriptor()).append(":").append(cv.getMessage()).append("=").append(cv.getInvalidValue()).append("]");
                }
                throw new RuntimeException(msg.toString(), e);
            }
            //service.getDao().flush();
            data.add(obj);
        }
    }
    
}
</#list>